package com.kaibes.core.base.util;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Pattern;

public class NetworkUtils {

    public static boolean isIp(String ip) {
        Pattern pattern = Pattern.compile("[0-9]{1,3}"+"\\."+"[0-9]{1,3}"+"\\."+"[0-9]{1,3}"+"\\."+"[0-9]{1,3}");
        return pattern.matcher(ip).matches();
    }
    
    /**
     * 获得指定域名的ip地址
     * 
     * @param hostName
     *            域名
     * @return 返回ip地址
     */
    public static String getIp(String hostName) {
        try {
            String ip = InetAddress.getByName(hostName).getHostAddress();
            return ip;
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        return "";
    }
    
    /**
     * 获得局域网ip
     * 
     * @return 返回局域网ip
     */
    public static String getAreaIp() {
        String ip = "127.0.0.1";
        try {
            Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();
            boolean isGo = true;
            while (en.hasMoreElements() && isGo) {
                NetworkInterface networkInterface = en.nextElement();
                Enumeration<InetAddress> enumeration = networkInterface.getInetAddresses();
                while (enumeration.hasMoreElements()) {
                    InetAddress inetAddress = enumeration.nextElement();
                    if (!inetAddress.isLoopbackAddress() && !inetAddress.isLinkLocalAddress()) {
                        ip = inetAddress.getHostAddress();
                        if (ip.length() <= 15) {
                            isGo = false;
                            break;
                        }
                    }
                }
            }
        } catch (SocketException e) {
//            e.printStackTrace();
        }

        return ip;
    }
    
    public static String getLocalHostAddress() {
        try {
            return InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
//            e.printStackTrace();
        }
        return "127.0.0.1";
    }
    
    public static int[] splitIp2Int(String ip) {
        int i = 0;
        int j = 0;

        int[] ipInts = new int[4];
        StringBuilder sbIp = new StringBuilder();
        for (; i < ip.length(); i++) {
            if (ip.charAt(i) == '.') {
                ipInts[j] = Integer.parseInt(sbIp.toString().trim(), 10);
                j++;
                sbIp.trimToSize();
                sbIp.setLength(0);
            } else {
                sbIp.append(ip.charAt(i));
            }
        }
        ipInts[j] = Integer.parseInt(sbIp.toString().trim(), 10);
        return ipInts;
    }

    public static String[] splitIp2String(String ip) {
        // ip.split(regex) 这个方法比较耗性能，所以不用这个方法
        int i = 0;
        int j = 0;
        String[] ipString = new String[4];
        StringBuilder sbIp = new StringBuilder();
        for (; i < ip.length(); i++) {
            if (ip.charAt(i) == '.') {
                ipString[j] = sbIp.toString().trim();
                j++;
                sbIp.trimToSize();
                sbIp.setLength(0);
            } else {
                sbIp.append(ip.charAt(i));
            }
        }
        ipString[j] = sbIp.toString().trim();
        return ipString;
    }
    
    public static long ip2Long(String ip) {
        long result = 0;
        String[] ipString = splitIp2String(ip);
        for (int i = 3; i >= 0; i--) {
            long ipLong = Long.parseLong(ipString[3 - i]);
            result |= ipLong << (i * 8);
        }
        return result;
    }
    
    public static String long2Ip(long l) {
        return ((l >> 24) & 0xFF) + "." + ((l >> 16) & 0xFF) + "." + ((l >> 8) & 0xFF) + "." + (l & 0xFF);
    }
    
    public static String findIpByPort(int port) {
        String[] ipStart = splitIp2String(getAreaIp());
        ipStart[3] = "1";
        StringBuilder sb = new StringBuilder();
        sb.append(ipStart[0]).append(".").append(ipStart[1]).append(".").append(ipStart[2]).append(".").append(ipStart[3]);
        return findIpByPort(sb.toString().trim(), port);
    }
    
    private static class FindIpString{
        private String ip = "";
        private boolean isFinding = true;
        
        public FindIpString() {
            // TODO Auto-generated constructor stub
        }
        
        public String getIp() {
            return ip;
        }
        public void setIp(String ip) {
            this.ip = ip;
        }
        public boolean isFinding() {
            return isFinding;
        }
        public void setFinding(boolean isFinding) {
            this.isFinding = isFinding;
        }

    }
    
    public static String findIpByPort(String start, String end, final int port) {
        long startTime = System.currentTimeMillis();
        long startIpLong = ip2Long(start);
        long endIpLong = ip2Long(end);
        final FindIpString isDoing = new FindIpString();
        ExecutorService executorService = Executors.newFixedThreadPool(255);
        for (;startIpLong<=endIpLong && isDoing.isFinding();startIpLong++) {
            final String ip = long2Ip(startIpLong);
            executorService.execute(new Runnable() {
                
                @Override
                public void run() {
                    while (isDoing.getIp().isEmpty()) {
                        Socket socket = new Socket();
                        try {
                            socket.connect(new InetSocketAddress(ip, port));
                            isDoing.setIp(ip);
                            isDoing.setFinding(false);
                        } catch (IOException e) {
                        }
                        try {
                            socket.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        while (isDoing.isFinding()) {
            if (System.currentTimeMillis() - startTime < 5 * 60 * 1000) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
                break;
            }
        }
        executorService.shutdownNow();
        System.err.println("end "+(System.currentTimeMillis() - startTime)/1000);
        return isDoing.getIp();
    }
    
    public static String findIpByPort(String start, int port) {
        String[] ipEnd = splitIp2String(start);
        ipEnd[3] = "255";
        StringBuilder sb = new StringBuilder();
        sb.append(ipEnd[0]).append(".").append(ipEnd[1]).append(".").append(ipEnd[2]).append(".").append(ipEnd[3]);
        return findIpByPort(start, sb.toString().trim(), port);
    }
    
}
